package com.sunday.framework.fegin.autoconfiguration;

import com.sunday.common.core.constants.LogConstants;
import com.sunday.common.core.remoting.rest.annotation.OpenApi;
import com.sunday.common.core.remoting.rest.annotation.VoErrorShowType;
import com.sunday.common.core.remoting.rest.response.RestExceptionResponse;
import com.sunday.framework.common.mvc.GlobalExceptionHandler;
import com.sunday.framework.common.mvc.WebConfiguration;
import com.sunday.framework.fegin.CurrentUserHolder;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * @Description: FEGIN 日志输出
 * <p>
 * 请求参数验证 - 默认实现 :
 * 1. 请求日志/响应日志
 */
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "sunday.framework.fegin", value = "execution")
@Import({GlobalExceptionHandler.class, WebConfiguration.class})
public class FeginAdvisorAutoConfiguration {

    @Bean
    public Advisor feginPointcutAdvisor(@Value("${sunday.framework.fegin.execution}") String execution) {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(execution);
        return new DefaultPointcutAdvisor(pointcut, (MethodInterceptor) invocation -> {
            Method method = invocation.getMethod();
            //获取方法上可能产生的注解
            VoErrorShowType voErrorShowType = method.getAnnotation(VoErrorShowType.class);
            OpenApi openApi = method.getAnnotation(OpenApi.class);
            try {
                /** 请求信息 日志打印 */
                log.info(LogConstants.request_format_aop,
                        Arrays.stream(invocation.getArguments()).map(String::valueOf).collect(Collectors.joining(",")),
                        method.getDeclaringClass(),
                        method.getName());
                /** 绑定当前登录人 */
                CurrentUserHolder.bind(openApi);
                /** 执行方法 */
                Object response = invocation.proceed();
                /** 响应信息 日志打印 */
                log.info(LogConstants.response_format_ack, response);
                return response;
            } catch (Throwable e) {
                return RestExceptionResponse.returnResponse(e, voErrorShowType);
            } finally {
                /** 解绑当前登录人 */
                CurrentUserHolder.unbind();
            }
        });
    }
}
